﻿//  --------------------------------
//  Copyright (c) 2010 Michael Schuler, Sascha Burger. All rights reserved.
//  This source code is made available under the terms of the Microsoft Public License (Ms-PL)
//  http://p2pmessaging.codeplex.com/license
//  ---------------------------------
using System;
using System.Collections.Generic;
using p2pMessaging.Interfaces.Contact;

namespace p2pMessaging.BL.Model
{
	/// <summary>
	/// Contact represents the data of a person.
	/// </summary>
	[Serializable]
	public sealed class Contact : IContact
	{
		private readonly List<IContact> myChildren;
		private string myId;
		private string myFirstName;
		private string myLastName;
		private string myStreet;
		private string myZipCode;
		private string myCity;
		private string myEmailAddress;
		private string myIpAddress;
		private IContact myParent;
		
		/// <summary>
		/// Initializes a new instance of the <see cref="Contact"/> class. 
		/// </summary>
		public Contact()
		{
			myId = Guid.NewGuid().ToString();
			myChildren = new List<IContact>();
		}

		/// <summary>
		/// Gets or sets the id of the persistence entity.
		/// </summary>
		public string Id
		{
			get { return myId; }
			set { myId = value; }
		}

		/// <summary>
		/// Gets or sets the first name of the contact.
		/// </summary>
		public string FirstName
		{
			get { return myFirstName ?? string.Empty; }
			set { myFirstName = value; }
		}
		
		/// <summary>
		/// Gets or sets the last name of the contact.
		/// </summary>
		public string LastName
		{
			get { return myLastName ?? string.Empty; }
			set { myLastName = value; }
		}

		/// <summary>
		/// Gets the display name of the contact. The display
		/// name contains the first and the last name.
		/// </summary>
		public string DisplayName
		{
			get { return string.Format("{0} {1}", FirstName, LastName); }
		}

		/// <summary>
		/// Gets or sets the street of the contact.
		/// </summary>
		public string Street
		{
			get
			{
				return string.IsNullOrEmpty(myStreet)
					? (myParent != null ? myParent.Street : string.Empty)
					: myStreet;
			}

			set
			{
				myStreet = value;
			}
		}

		/// <summary>
		/// Gets or sets the zip code of the contact.
		/// </summary>
		public string ZipCode
		{
			get
			{
				return string.IsNullOrEmpty(myZipCode)
					? (myParent != null ? myParent.ZipCode : string.Empty)
					: myZipCode;
			}
			
			set
			{
				myZipCode = value;
			}
		}

		/// <summary>
		/// Gets or sets the city of the contact.
		/// </summary>
		public string City
		{
			get
			{
				return string.IsNullOrEmpty(myCity)
					? (myParent != null ? myParent.City : string.Empty)
					: myCity;
			}

			set
			{
				myCity = value;
			}
		}

		/// <summary>
		/// Gets or sets the email address of the contact.
		/// </summary>
		public string EmailAddress
		{
			get
			{
				return string.IsNullOrEmpty(myEmailAddress)
					? (myParent != null ? myParent.EmailAddress : string.Empty)
					: myEmailAddress;
			}

			set
			{
				myEmailAddress = value;
			}
		}

		/// <summary>
		/// Gets or sets the IP address of the contact.
		/// </summary>
		public string IpAddress
		{
			get
			{
				return string.IsNullOrEmpty(myIpAddress)
					? (myParent != null ? myParent.IpAddress : string.Empty)
					: myIpAddress;
			}
			
			set
			{
				myIpAddress = value;
			}
		}

		/// <summary>
		/// Gets or sets the parent of the contact. Can be null.
		/// </summary>
		public IContact Parent
		{
			get { return myParent; }
			set { myParent = value; }
		}

		/// <summary>
		/// Gets the children of the contact. This list can be empty.
		/// </summary>
		public IList<IContact> Children
		{
			get { return myChildren; }
		}

		public int CompareTo(IContact other)
		{
			return DisplayName.CompareTo(other.DisplayName);
		}

		public override bool Equals(object obj)
		{
			return Equals(obj as IContact);
		}

		public override int GetHashCode()
		{
			if (string.IsNullOrEmpty(Id))
			{
				return base.GetHashCode();
			}
			
			return Id.GetHashCode();
		}

		public bool Equals(IContact other)
		{
			if (other == null)
			{
				return false;
			}
			
			return Id.Equals(other.Id) &&
				FirstName.Equals(other.FirstName) &&
				LastName.Equals(other.LastName) &&
				Street.Equals(other.Street) &&
				ZipCode.Equals(other.ZipCode) &&
				City.Equals(other.City) &&
				EmailAddress.Equals(other.EmailAddress) &&
				IpAddress.Equals(other.IpAddress);
		}
	}
}
